package com.sky.business.sys.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sky.business.sys.domain.*;
import com.sky.business.sys.param.NodeListParam;
import com.sky.business.sys.param.NodeParam;
import com.sky.business.sys.param.NodeReadyParam;
import com.sky.business.sys.service.*;
import com.sky.business.sys.vo.NodeVo;
import com.sky.common.api.Result;
import com.sky.common.enums.TaskType;
import com.sky.common.utils.NetworkUtil;
import com.sky.common.utils.StringUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/node")
@Tag(name = "节点管理", description = "节点管理")
@Slf4j
public class NodeController {

    @Autowired
    private NodeService nodeService;

    @Autowired
    private ContainerConfigService containerConfigService;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private GroupService groupService;

    @Operation(summary = "节点列表")
    @PostMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<Map<String, Object>> list(@RequestBody NodeListParam param) {

        List<NodeVo> voList = new ArrayList<>();

        List<Group> groups = groupService.list();

        Map<Integer, Group> groupMap = groups.stream().collect(Collectors.toMap(Group::getId, g -> g));

        LambdaQueryWrapper<Node> wrapper = new LambdaQueryWrapper<>();
        if(StringUtils.isNotBlank(param.getContent())){
            wrapper.likeLeft(Node::getIpAddr, param.getContent()).or().likeLeft(Node::getDescription, param.getContent());
        }
        if(param.getGroupId() != null){
            wrapper.eq(Node::getGroupId, param.getGroupId());
        }
        wrapper.eq(Node::getIsDel, false);


        IPage<Node> iPage = nodeService.page(new Page<>(param.getPage(), param.getLimit()), wrapper);
        List<Node> nodes = iPage.getRecords();
        Group group;
        for(Node node : nodes){
            group = groupMap.get(node.getGroupId());
            NodeVo vo = new NodeVo(node, group != null ? group.getName() : null);
            voList.add(vo);
        }
        Map<String, Object> data = new HashMap<>(2);
        data.put("records", voList);
        data.put("total", iPage.getTotal());
        return Result.success(data);
    }

    @Operation(summary = "新增节点")
    @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<Object> add(@RequestBody NodeParam param) {

        LambdaQueryWrapper<Node> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Node::getIpAddr, param.getIpAddr()).eq(Node::getIsDel, false);

        Node node = nodeService.getOne(wrapper);
        if(node != null){
            return Result.failed("IP地址已存在");
        }

        boolean reachable = NetworkUtil.isReachable(param.getIpAddr(), param.getContainerPort(), 500);
        if (!reachable) {
            return Result.failed("节点端口不通");
        }
        node = new Node();
        node.setArch(param.getArch());
        node.setDescription(param.getDescription());
        node.setIpAddr(param.getIpAddr());
        node.setContainerPort(param.getContainerPort());
        node.setGpuCount(param.getGpuCount());
        node.setGroupId(param.getGroupId());
        node.setReady(param.getReady());
        nodeService.save(node);
        //启动监控程序
        SystemConfig systemConfig =systemConfigService.getSystemConfig();
        List<ContainerConfig> containerConfigList = containerConfigService.findByTaskTypeAndArch(TaskType.MONITOR,node.getArch());
        if(containerConfigList.isEmpty()){
            log.error("监控任务无法启动,暂无与节点匹配的镜像.节点id:{}, cpu架构:{}",node.getId(),node.getArch());
        }else{
            ContainerConfig containerConfig = containerConfigList.get(0);
            taskService.startMonitorTask(systemConfig,node,containerConfig);
        }
        return Result.success();
    }

    @Operation(summary = "编辑节点信息")
    @PostMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<Object> update(@RequestBody NodeParam param) {

        LambdaQueryWrapper<Node> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Node::getIpAddr, param.getIpAddr()).eq(Node::getIsDel, false).ne(Node::getId, param.getId());

        Node node = nodeService.getOne(wrapper);
        if(node != null){
            return Result.failed("IP地址已存在");
        }

        boolean reachable = NetworkUtil.isReachable(param.getIpAddr(), param.getContainerPort(), 500);
        if (!reachable) {
            return Result.failed("节点端口不通");
        }
        node = nodeService.getById(param.getId());
        node.setArch(param.getArch());
        node.setDescription(param.getDescription());
        node.setIpAddr(param.getIpAddr());
        node.setContainerPort(param.getContainerPort());
        node.setGroupId(param.getGroupId());
        node.setGpuCount(param.getGpuCount());
        node.setReady(param.getReady());
        nodeService.updateById(node);
        //删除旧的容器,启动新容器
        SystemConfig systemConfig =systemConfigService.getSystemConfig();
        List<ContainerConfig> containerConfigList = containerConfigService.findByTaskTypeAndArch(TaskType.MONITOR,node.getArch());
        if(containerConfigList.isEmpty()){
            log.error("监控任务无法启动,暂无与节点匹配的镜像.节点id:{}, cpu架构:{}",node.getId(),node.getArch());
        }else{
            ContainerConfig containerConfig = containerConfigList.get(0);
            taskService.startMonitorTask(systemConfig,node,containerConfig);
        }
        return Result.success();
    }

    @Operation(summary = "删除节点")
    @GetMapping(value = "/del", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<Object> del(@RequestParam("id") Integer id) {
        //删除监控任务
        Node node = nodeService.getById(id);
        taskService.removeMonitorTask(node);
        LambdaUpdateWrapper<Node> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Node::getIsDel, true).eq(Node::getId, id);
        nodeService.update(updateWrapper);
        return Result.success();
    }

    @Operation(summary = "更改节点ready状态")
    @PostMapping(value = "/readyChange", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<Object> readyChange(@RequestBody NodeReadyParam param) {
        LambdaUpdateWrapper<Node> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Node::getReady, param.getReady()).eq(Node::getId, param.getId());
        nodeService.update(updateWrapper);
        return Result.success();
    }


}
